/**
 * Copyright (c) 2008, EffCode, www.effcode.com
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list 
 * of conditions and the following disclaimer. 
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution. 
 * Neither the name of the EffCode nor the names of its contributors may be used 
 * to endorse or promote products derived from this software without specific prior written 
 * permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.effdom;

/**
 * The <code>Document</code> is the envelop for a set of EffDom data. The
 * <code>Document</code> can only contain one and only one
 * <code>Element</code> - the root element. The <code>Document</code> is
 * populated with data by adding attributes and elements to the root element.
 * <p/> <code>Documents</code> are created by using the
 * <code>DocumentFactory's</code> method <code>createDocument()</code>
 * <p>
 * 
 * <pre><code>
 * Document doc = DocumentFactory.createInstance().createDocument();
 * </code></pre>
 * 
 * </p>
 * 
 * The root element is used to append data to the <code>Document</code>. The
 * root element is created together with an ID that identifies the root element
 * among others.
 * <p>
 * 
 * <code><pre>
 * 
 *    //  Init IDs for elements and attributes. 
 *    //  Valid datatypes are: byte or short, if id is set to short but is within range 
 *    //  Byte.MIN and Byte.MAX it is automatically changed to byte when packed and sent. 
 * 
 *    public final static short PERSON = 1;
 * 
 *    public final static short ADDRESS = 2;
 * 
 *    public final static short FIRST_NAME = 3;
 * 
 *    public final static short LAST_NAME = 4;
 * 
 *    public final static short AGE = 5;
 * 
 *    public final static short ZIP = 6;
 * 
 *    public final static short CITY = 7;
 * 
 *    public final static short ROAD = 8;
 * 
 *    public final static short PICTURE = 9;
 * 
 *    public final static short VALUE = 10;
 * 
 *    public final static short MIME_TYPE = 11;
 * 
 *    public final static short DESCRIPTION = 12;
 * 
 *    ....
 * 
 *    //  The method createPersonDocument() supposes to return an document describing the person John Smith. The
 *    //  document will hold and element for the person with attributes for name. Address 
 *    //  and personal portrait prictures will also be added. The structre would look like this:
 * 
 *    //  &lt;person firstName=&quot;John&quot; lastName=&quot;Smith&quot; age=&quot;32&quot;&gt;
 *    //    &lt;address road=&quot;Bellsroad 9&quot; zip=&quot;45642&quot; city=&quot;Fantasia&quot; /&gt; 
 *    //    &lt;picture description=&quot;Portrait side&quot; value=&quot;Binary data size=3410&quot; mimeType=&quot;image/jpeg&quot; /&gt;
 *    //    &lt;picture decription=&quot;Portrait front&quot; value=&quot;Binary data size=2456&quot; mimeType=&quot;image/jpeg&quot; /&gt;
 *    //  &lt;/person&gt;
 * 
 *    public Document createPersonDocument() {
 *   
 *      //  Create the document
 *   
 *      Document doc = DocumentFactory.createInstance().createDocument();
 *   
 *   
 *      //  Create the root element and give it the PERSON ID
 *   
 *      Element personElem = doc.rootElement(PERSON);
 *   
 *   
 *      //  Create and add attributes for first and last name and age. Note that the age is a number. 
 *   
 *      personElem.attr(FIRST_NAME, &quot;John&quot;);
 *      personElem.attr(LAST_NAME,  &quot;Smith&quot;);
 *      personElem.attr(AGE, 32);
 *   
 *   
 *      //  Create the element ADDRESS and append it to the root element
 *   
 *      Element addressElem = personElem.element(ADDRESS);
 *   
 *   
 *      //  Add road, zip and city attributes to the address element
 *      //  Due to the fact that the attr() method returns the current element it is possible
 *      //  to add several attributes in a chain
 *   
 *      addressElem.attr(ROAD, &quot;Bellsroad 9&quot;)
 *                 .attr(ZIP,  &quot;12345&quot;)
 *                 .attr(CITY, &quot;Fantasia&quot;);
 *   
 *   
 *      //  Create two elements for portrait images and append them to the root element. The element()
 *      //  metod returns the newly created and added element.
 *      //  Add an description, raw image data and mime type attributes. Note that the image data is a binary
 *      //  byte array
 *   
 *      personElem.element(PICTURE)
 *                .attr(DESCRIPTION, &quot;Portrait side&quot;)
 *                .attr(VALUE,       imageDataSide)
 *                .attr(MIME_TYPE,   &quot;image/jpeg&quot;);
 *   
 *      personElem.element(PICTURE)
 *                .attr(DESCRIPTION, &quot;Portrait front&quot;)
 *                .attr(VALUE,       imageDataFront)
 *                .attr(MIME_TYPE,   &quot;image/jpeg&quot;);
 *   
 *      
 *      return doc;
 *    }
 *   
 * </pre></code>
 * 
 * To log, debug or just display a <code>Document</code> content, just call
 * the toString() method. <br/><br/> Calling toString() on the document in the
 * example above would look like. <code><pre>
 *      
 *    Document version=1
 *    &lt;1 3=&quot;John&quot; 4=&quot;Smith&quot; 5=&quot;32&quot; &gt;
 *      &lt;2 8=&quot;Bellsroad 9&quot; 6=&quot;12345&quot; 7=&quot;Fantasia&quot;&gt;&lt;/2&gt;
 *      &lt;9 12=&quot;Portrait side&quot; 10=&quot;Binary value. Size=1234&quot; 11=&quot;image/jpeg&quot;&gt;&lt;/9&gt;
 *      &lt;9 12=&quot;Portrait front&quot; 10=&quot;Binary value. Size=4321&quot; 11=&quot;image/jpeg&quot;&gt;&lt;/9&gt;
 *    &lt;/1&gt;
 *    
 * </pre>
 * </code> Binary values are only displayed with type and length.
 * 
 * </p>
 * 
 * @author <a href="mailto:mattias@effcode.com">Mattias Jonsson</a>
 */
public interface Document {

    /**
     * Return the root element for this <code>Document</code>. There can only
     * be one root element per document.
     * 
     * @return the document's root element or Null if no root element is added.
     */
    public Element rootElement();

    /**
     * EffDom protocol version for this document. The version will
     * correspond to version of EffDom protcol to use to pack this document to
     * an byte array.
     * 
     * @return the document implementation version.
     */
    public byte version();

    /**
     * Creates and adds the root element for this document. The ID specfies the
     * root element identification.
     * 
     * @param id
     *            the root element ID
     * @return the newly created root element
     */
    public Element rootElement(short id);
    

    /**
     * Set the root element for this document.
     * 
     * @param element
     *            the root element
     * @return the root element
     */
    public Element rootElement(Element element);
}
